
import spinal.core._
import spinal.lib._
import spinal.lib.fsm._


/*
问题说明,由于运行在50MHz的频率下,所以会出现特殊情况.


    A.  dat接收结束时,crc16 之前多接收一位?
        *注,以解决,烧录FPGA的时候,需要关闭一些连接SOC的调试器 (使用了新接口的crc16计算)
    B.  设备是在sck上升沿时推送数据,所以主机应该在下降沿的时候获得数据
        或者接收数据时,再2分频


*/


class DataShiftStatus(width:Int){
    val w = width + 1
    val recv_dat = Reg(Bits(w bits)) init(1)
    def init(){
        recv_dat := 1
    }
    def push(dat:Bits){
        recv_dat(w-1 downto dat.getWidth) := recv_dat(w-dat.getWidth-1 downto 0)
        recv_dat(dat.getWidth-1 downto 0) := dat
    }
    def full(): Bool = {
        recv_dat(w-1)
    }
}

case class sdio_crc16() extends Component {
    val io = new Bundle {
        val sdio_clk    = in Bool()
        val sdio_line   = in Bool()
        val calc_en     = in Bool()
        val line_reset  = in Bool()
        val line_crc16  = out Bits(16 bits)
    }

    val crc = Reg(Bits(16 bits)) init(0)
    val polynomial = U"x1021"
    val crc_shift = crc ## B"0"
    val crc_calc = crc_shift(15 downto 0) ^ Mux(crc(15),polynomial.asBits,(U"x0000").asBits)

    io.line_crc16 := crc;

    /*错误有点多,使用其他方案来*/
    when(io.line_reset){
        crc := 0;
    }.elsewhen(io.sdio_clk.rise && io.calc_en){
        //计算
        crc := crc_calc(15 downto 0) ^ Mux(io.sdio_line,polynomial.asBits,(U"x0000").asBits)
    }

    //方案2
    // def reset(){
    //     crc := 0;
    // }

    // when(io.line_reset){
    //     crc := 0
    // }

    // def calc(){
    //     crc := crc_calc(15 downto 0) ^ Mux(io.sdio_line,polynomial.asBits,(U"x0000").asBits)
    // }
}

class sdio_crc16d(signal:Bool,id:Int){
    val crc = Reg(Bits(16 bits)) init(0)
    val name = s"crc16_p$id"
    crc.setName(name)
    val polynomial = U"x1021"
    val crc_shift = crc ## B"0"
    //val signal_nt   = RegNext(signal)
    val crc_calc    = crc_shift(15 downto 0) ^ Mux(crc(15),polynomial.asBits,(U"x0000").asBits)
    def reset(){
        crc := 0
    }
    def calc(){
        crc := crc_calc(15 downto 0) ^ Mux(signal,polynomial.asBits,(U"x0000").asBits)
    }
}

class sdio_crc8d(signal:Bool){
    val crc = Reg(Bits(8 bits)) init(0)
    crc.setName("crc8d")
    val polynomial = U"x09"
    val crc_shift = crc ## B"0"
    val crc_calc = crc_shift(7 downto 0)
    val crc_calc_signal = crc_calc(7) ^ signal
    def reset(){
        crc := 0
    }
    def calc(){
        crc := crc_calc ^ Mux(crc_calc_signal,polynomial.asBits,(U"x00").asBits)
    }
}

case class sdio_crc8() extends Component {
    val io = new Bundle {
        val sdio_clk    = in Bool()
        val sdio_line   = in Bits(1 bits)
        val calc_en     = in Bool()
        val crc_reset   = in Bool()
        val crc_out     = out Bits(8 bits)
        val crc_in      = in Bits(8 bits)
    }

    val crc = Reg(Bits(8 bits)) init(0)
    val polynomial = U"x09"
    val crc_shift = io.crc_in ## B"0"
    val crc_calc = crc_shift(7 downto 0)
    val line = (io.sdio_line)
    val crc_calc_signal = crc_calc(7) ^ line.asBool


    io.crc_out := crc;

    when(io.crc_reset){
        crc := 0;
    }.elsewhen(io.sdio_clk.rise && io.calc_en){
        //计算
        crc := crc_calc ^ Mux(crc_calc_signal,polynomial.asBits,(U"x00").asBits)
    }
}

class crc8(clk:Bool,signal:Bits){
    val en    = Reg(Bool)   init(False)     //默认关闭
    val rst   = Reg(Bool)   init(False)
    val crc   = Bits(8 bits)
    val u_crc = new sdio_crc8;

    crc := u_crc.io.crc_out
    u_crc.io.sdio_clk  := clk
    u_crc.io.sdio_line := signal
    u_crc.io.calc_en   := en
    u_crc.io.crc_in    := u_crc.io.crc_out
    u_crc.io.crc_reset := rst
}

class line_crc(clk:Bool,signal:Bool,rst:Bool,en:Bool){
    val crc_d = new sdio_crc16
    //val en  = Reg(Bool) init(True)
    //val rst = new Reg(Bool) init(False)
    val crc = Bits(16 bits)
    crc_d.io.sdio_clk     := clk
    crc_d.io.sdio_line    := signal
    crc_d.io.line_reset   := rst
    crc_d.io.calc_en      := en
    crc :=  crc_d.io.line_crc16
}

class lines_crc(clk:Bool,signal:Bits){
    val rst = Reg(Bool) init(False)
    val en =  Reg(Bool) init(False)
    val line0 = new line_crc(clk,signal(0),rst,en)
    val line1 = new line_crc(clk,signal(1),rst,en)
    val line2 = new line_crc(clk,signal(2),rst,en)
    val line3 = new line_crc(clk,signal(3),rst,en)
    val flg = Reg(Bool) init(False)

    val crc0 = Reg(Bits(16 bits)) init(0)
    val crc1 = Reg(Bits(16 bits)) init(0)
    val crc2 = Reg(Bits(16 bits)) init(0)
    val crc3 = Reg(Bits(16 bits)) init(0)

    val recv0 = Reg(Bits(16 bits)) init(0)
    val recv1 = Reg(Bits(16 bits)) init(0)
    val recv2 = Reg(Bits(16 bits)) init(0)
    val recv3 = Reg(Bits(16 bits)) init(0)

    val l0 = new sdio_crc16d(signal(0),0)
    val l1 = new sdio_crc16d(signal(1),1)
    val l2 = new sdio_crc16d(signal(2),2)
    val l3 = new sdio_crc16d(signal(3),3)

    crc0.setName("crc0")
    crc1.setName("crc1")
    crc2.setName("crc2")
    crc3.setName("crc3")
    flg.setName("debug_flg")

    recv0.setName("recv0")
    recv1.setName("recv1")
    recv2.setName("recv2")
    recv3.setName("recv3")

    val ok4 =
        crc0===recv0 &&
        crc1===recv1 &&
        crc2===recv2 &&
        crc3===recv3
    val fail4 =
        crc0=/=recv0 ||
        crc1=/=recv1 ||
        crc2=/=recv2 ||
        crc3=/=recv3

    val ok1   = crc0===recv0;
    val fail1 = crc0=/=recv0


    val eok4 =
        l0.crc===recv0 &&
        l1.crc===recv1 &&
        l2.crc===recv2 &&
        l3.crc===recv3
    val efail4 =
        l0.crc=/=recv0 ||
        l1.crc=/=recv1 ||
        l2.crc=/=recv2 ||
        l3.crc=/=recv3

    val eok1   = l0.crc===recv0
    val efail1 = l0.crc=/=recv0

    //重置
    def reset(){
        l0.reset()
        l1.reset()
        l2.reset()
        l3.reset()
    }

    def set(){
        crc0 := line0.crc
        crc1 := line1.crc
        crc2 := line2.crc
        crc3 := line3.crc
        flg := True
    }

    def calc(){
        l0.calc()
        l1.calc()
        l2.calc()
        l3.calc()
    }

    def recv(){
        recv0   :=  recv0(recv0.high-1 downto 0) ## signal(0)
        recv1   :=  recv1(recv1.high-1 downto 0) ## signal(1)
        recv2   :=  recv2(recv2.high-1 downto 0) ## signal(2)
        recv3   :=  recv3(recv3.high-1 downto 0) ## signal(3)
        flg := False
    }

    def ok(bus_4bit:Bool):Bool = {
        Mux(bus_4bit,eok4,eok1)
    }

    def fail(bus_4bit:Bool):Bool = {
        Mux(bus_4bit,efail4,efail1)
    }
}

case class sdio_ctrl() extends Component{
    val io = new Bundle {
        val sdio_clk = out Bool()
        val sdio_cmd = inout(Analog(Bits(1 bits)))
        val sdio_dat = inout(Analog(Bits(4 bits)))

        //时钟
        val sdio_clkdiv   = in SInt(8 bits)

        //发送
        val cmd_en    = in Bool()
        val cmd       = in Bits(6 bits)
        val cmd_done  = out Bool()
        val argu      = in Bits(32 bits)
        val cmd_busy  = out Bool()
        val need_rsp  = in Bool()
        val long_rsp  = in Bool()
        val bus_4bit  = in Bool()
        val mmc_init = in Bool()

        val rsp = out Bits(256 bits)
        val crc_rsp_ok = out Bool()
        val crc_rsp_fail = out Bool()

        val crc_dat_ok = out Bool()
        val crc_dat_fail = out Bool()
        //val cmd_crc_rst = in Bool()

        val recv_stream = master Stream(Bits(32 bits))
        val send_stream = slave  Stream(Bits(32 bits))
        val block_size = in SInt(16 bits)
        val wait_rsp = out Bool()
        val wait_is_rsp = out Bool()

        val data_en = in Bool()
        val data_write = in Bool()
        val dat_next_en       = in Bool()
    }

    val clk_cnt = Reg(SInt(8 bits)) init(0)
    when(clk_cnt<io.sdio_clkdiv){
        clk_cnt := clk_cnt + 1
    }.otherwise{
        clk_cnt := 0
    }

    //控制输入输出
    val dat_o  = Reg(Bits(4 bits)) init(0)
    val dat_oe = Reg(Bool) init(False)
    val cmd_o  = Reg(Bool) init(True)
    val cmd_oe = Reg(Bool) init(False)

    when(cmd_oe){
        io.sdio_cmd := cmd_o.asBits
    }

    when(dat_oe){
        io.sdio_dat := dat_o
    }

    val sdio_clk = Reg(Bool) init(True)
    val clk_edge = clk_cnt===io.sdio_clkdiv
    val clk_hi = sdio_clk
    val clk_lo = ~sdio_clk
    io.sdio_clk := sdio_clk

    def update_clk_to_hi(body : => Unit){
        when(clk_lo){
            when(clk_edge){
                sdio_clk := ~sdio_clk
                body
            }
        }
    }

    def update_clk_to_lo(body: => Unit){
        when(clk_hi){
            when(clk_edge){
                sdio_clk := ~sdio_clk
                body
            }
        }
    }

    val dat_rsp = Reg(Bits(8 bits)) init(0)
    dat_rsp.setName("dat_rsp")

    val cmd_done = Reg(Bool) init(False)
    val cmd_seq = B"2'b01" ## io.cmd ## io.argu(31 downto 0)
    val cmd_dat = Reg(Bits(40 bits)) init(0)
    val cmd_remaining = Reg(SInt(8 bits)) init(0)
    val wait_remaining = Reg(SInt(8 bits))init(0)
    val rsp_remaining = Reg(SInt(9 bits)) init(0)
    val cmd_crc = new crc8(io.sdio_clk,io.sdio_cmd)
    val cmd_crcd = new sdio_crc8d(io.sdio_cmd.asBool)
    val rsp = Reg(Bits(256 bits))init(0)
    val rsp_crc = Reg(Bits(8 bits)) init(0)
    rsp_crc.setName("rsp_crc")
    io.rsp := rsp
    io.cmd_done := cmd_done

    val crc_rsp_ok   = Reg(Bool) init(False)
    val crc_rsp_fail = Reg(Bool) init(False)
    io.crc_rsp_ok   := crc_rsp_ok
    io.crc_rsp_fail := crc_rsp_fail

    val block_remaining = Reg(SInt(16 bits)) init(0)
    val send_remaining = Reg(SInt(8 bits))init(0)
    val l_crc = new lines_crc(io.sdio_clk,io.sdio_dat)
    val send_payload = Reg(Bits(32 bits)) init(0)
    val send_payload_trg = Reg(Bool) init(False)
    io.send_stream.ready := send_payload_trg.edge

    val crc_dat_ok = Reg(Bool) init(False)
    val crc_dat_fail = Reg(Bool) init(False)
    io.crc_dat_ok   := crc_dat_ok
    io.crc_dat_fail := crc_dat_fail

    val fsm = new StateMachine {
        always{
            when(io.mmc_init.rise){
                wait_remaining := 127
                cmd_done := False
                goto(mmc_init)
            }
        }
        val idle: State = new State with EntryPoint {
            whenIsActive{
                update_clk_to_hi{}
                cmd_oe := False
                dat_oe := False
                when(io.mmc_init.rise){
                    wait_remaining := 127
                    cmd_done := False
                    goto(mmc_init)
                }
                .elsewhen(io.cmd_en.rise){
                    cmd_done    := False
                    goto(cmd_init)
                }
                .elsewhen(io.dat_next_en.rise){
                    when(!io.data_write){
                        goto(dat_recv_wait)
                    }
                    .otherwise{
                        //应该在idle状态下等待io.send_stream.valid
                    }
                }
                .elsewhen(io.send_stream.valid){
                    //存在需要发送的数据
                    l_crc.rst := True
                    goto(dat_write_wait)
                }
            }
        }
        val cmd_init:State = new State{
            whenIsActive{
                cmd_crcd.reset();
                cmd_remaining := 40
                cmd_crc.rst := True
                cmd_crc.en  := True
                cmd_oe  := True
                cmd_dat := cmd_seq
                goto(send_cmd)
            }
        }
        val mmc_init:State = new State{
            whenIsActive{
                when(wait_remaining>=0){
                    update_clk_to_lo{}
                    update_clk_to_hi{
                        wait_remaining := wait_remaining - 1
                    }
                }
                .otherwise{
                    cmd_done := True
                    goto(idle)
                }
            }
        }
        //发送命令
        val send_cmd: State = new State{
            whenIsActive{
                when(cmd_remaining>=0){
                    cmd_crc.rst := False
                    cmd_crc.en  := True
                    update_clk_to_lo{
                        cmd_remaining   := cmd_remaining - 1
                        cmd_o           := cmd_dat.msb
                        cmd_dat         := cmd_dat(cmd_dat.high-1 downto 0) ## B"1"
                    }
                    update_clk_to_hi{}
                }
                .otherwise{
                    wait_remaining := 6
                    goto(send_crc)
                }
            }
        }

        val send_crc: State = new State{
            whenIsActive{
                when(wait_remaining>0){
                    wait_remaining := wait_remaining - 1;
                    cmd_dat(7 downto 0) := cmd_crc.crc(6 downto 0) ## B"1"
                    cmd_dat(cmd_dat.high downto 8) := 1
                }
                .otherwise{
                    when(!cmd_dat(20)){
                        //发送crc数据
                        cmd_o       := cmd_dat(7)
                        update_clk_to_lo{
                            cmd_dat     := cmd_dat(cmd_dat.high-1 downto 0) ## B"1"
                        }
                        update_clk_to_hi{}
                    }
                    .otherwise{
                        when(io.need_rsp){
                            goto(rsp_wait)
                        }
                        .otherwise{
                            cmd_done := True
                            goto(idle)
                        }
                    }
                }
            }
        }

        val rsp_recv:State = new State{
            whenIsActive{
                when(rsp_remaining===129){
                    cmd_crc.en := True
                }
                when(rsp_remaining>9){
                    wait_remaining := 4
                    update_clk_to_hi{}
                    update_clk_to_lo{
                        rsp_remaining := rsp_remaining - 1
                        rsp := rsp(rsp.high-1 downto 0) ## io.sdio_cmd
                        cmd_crcd.calc()
                    }
                }
                .elsewhen(wait_remaining>=0){
                    //获得计算的crc
                    rsp_crc         := cmd_crc.crc
                    cmd_crc.en      := False
                    wait_remaining  := wait_remaining - 1
                }
                .elsewhen(rsp_remaining>=0){
                    //开始接收crc
                    update_clk_to_lo{
                        rsp_remaining := rsp_remaining - 1
                        when(rsp_remaining>1){
                            rsp := rsp(rsp.high-1 downto 0) ## io.sdio_cmd
                        }
                    }
                    update_clk_to_hi{}
                }
                .otherwise{
                    crc_rsp_ok      := (rsp(7 downto 1) === rsp_crc(6 downto 0)) || (rsp(7 downto 0)===0xff)
                    crc_rsp_fail    := (rsp(7 downto 1) =/= rsp_crc(6 downto 0)) && (rsp(7 downto 0)=/=0xff)

                    when(io.long_rsp){
                        //需要再位移8位,rsp包括crc8, 127~0
                        rsp := rsp(rsp.high-8 downto 0) ## B"8'd0"
                    }
                    cmd_done := True
                    when(io.data_en && !io.data_write){
                        goto(dat_recv_wait)
                    }
                    .otherwise{
                        goto(idle)
                    }
                }
            }
        }

        val dat_recv_wait:State = new State{
            whenIsActive{
                recv_stream_payload :=  ~B("33'd0")
                block_remaining     :=  io.block_size |>> 2         //每次传输4个字节
                update_clk_to_lo{
                    //如果是低电平,则开始接收数据
                    when(!io.sdio_dat(0)){
                        l_crc.reset()           //重置crc
                        l_crc.rst := False
                        l_crc.en  := True
                        goto(dat_recv)
                    }
                    .otherwise{
                        crc_dat_ok   :=False
                        crc_dat_fail := False
                        l_crc.en  := True
                        l_crc.rst := True
                    }
                }
                update_clk_to_hi{}
            }
        }

        val dat_recv:State = new State{
            whenIsActive{
                when(block_remaining>=0){
                    when(!recv_stream_payload.msb){
                        update_clk_to_lo{
                            l_crc.calc() //计算crc
                            when(io.bus_4bit){
                                recv_stream_payload := recv_stream_payload(recv_stream_payload.high-4 downto 0) ## io.sdio_dat
                            }
                            .otherwise{
                                recv_stream_payload := recv_stream_payload(recv_stream_payload.high-1 downto 0) ## io.sdio_dat(0)
                            }
                        }
                        update_clk_to_hi{}
                    }
                    .elsewhen(!io.recv_stream.valid && io.recv_stream.ready){
                        //触发一次读取
                        block_remaining     := block_remaining - 1
                        recv_stream_payload := 1
                    }
                }
                .otherwise{
                    wait_remaining := 20
                    goto(dat_recv_crc)
                }
            }
        }

        val dat_recv_crc:State = new State{
            whenIsActive{
                when(wait_remaining>17){
                    wait_remaining := wait_remaining -1
                    l_crc.set()
                }
                .elsewhen(wait_remaining>=0){
                    update_clk_to_lo{
                        wait_remaining := wait_remaining - 1
                    }
                    update_clk_to_hi {
                        when(wait_remaining>0){
                            l_crc.recv()            //接收数据
                        }
                    }
                }
                .otherwise{
                    crc_dat_ok      :=   l_crc.ok(io.bus_4bit)
                    crc_dat_fail    := l_crc.fail(io.bus_4bit)
                    goto(idle)
                }
            }
        }

        val rsp_wait:State = new State{
            whenIsActive{
                cmd_crc.en      := !io.long_rsp     //
                crc_rsp_ok      := False
                crc_rsp_fail    := False
                cmd_oe          := False
                rsp             := 0
                rsp_remaining   := Mux(io.long_rsp,S"d136",S"d48")
                update_clk_to_hi{
                    when(io.sdio_cmd===0){
                        cmd_crc.rst := False
                        goto(rsp_recv)
                    }
                    .otherwise{
                        cmd_crc.rst := True
                    }
                }
                update_clk_to_lo{}
            }
        }

        val dat_write:State = new State{
            whenIsActive{
                when(send_remaining>=0){
                    update_clk_to_lo{
                        dat_o   := send_payload.resizeLeft(4)
                        when(io.bus_4bit){
                            send_payload := send_payload |<< 4
                        }
                        .otherwise{
                            send_payload := send_payload |<< 1
                        }
                    }
                    update_clk_to_hi{
                        send_remaining := send_remaining - 1
                    }
                }
                .elsewhen(block_remaining<=0){
                    wait_remaining := 20
                    goto(dat_write_crc)
                }
                .elsewhen(io.send_stream.valid){
                    send_payload_trg    := !send_payload_trg
                    send_payload        := io.send_stream.payload
                    //when(~sdio_clk){
                    send_remaining      := Mux(io.bus_4bit,S"8'd7",S"8'd31")
                    //}
                    block_remaining     := block_remaining - 1
                }
            }
        }
        val dat_write_crc:State = new State{
            whenIsActive{
                when(wait_remaining>16){
                    wait_remaining := wait_remaining - 1
                    l_crc.set()
                }
                .elsewhen(wait_remaining>=0){
                    update_clk_to_lo{
                        //写crc数据
                        wait_remaining := wait_remaining - 1
                        dat_o(0) := l_crc.crc0.msb
                        dat_o(1) := l_crc.crc1.msb
                        dat_o(2) := l_crc.crc2.msb
                        dat_o(3) := l_crc.crc3.msb
                        l_crc.crc0 := l_crc.crc0(14 downto 0) ## B"1"
                        l_crc.crc1 := l_crc.crc1(14 downto 0) ## B"1"
                        l_crc.crc2 := l_crc.crc2(14 downto 0) ## B"1"
                        l_crc.crc3 := l_crc.crc3(14 downto 0) ## B"1"
                    }
                    update_clk_to_hi{}
                }
                .otherwise{
                    dat_rsp := ~B"8'd0"
                    wait_remaining := 0
                    goto(dat_write_rsp)
                }
            }
        }
        val dat_write_rsp:State = new State{
            whenIsActive{
                dat_oe := False
                when(wait_remaining>0){
                    update_clk_to_lo{
                        wait_remaining := wait_remaining - 1
                    }
                    update_clk_to_hi{}
                    when(wait_remaining===1){
                        crc_dat_ok      := dat_rsp(6 downto 4)===B"010"
                        crc_dat_fail    := dat_rsp(6 downto 4)=/=B"010"
                        goto(idle)
                    }
                }
                .otherwise{
                    update_clk_to_lo{
                        when(dat_rsp(7).asUInt =/=0){
                            //等待回复
                            dat_rsp := dat_rsp(6 downto 0) ## io.sdio_dat(0)
                        }
                        .otherwise{
                            when(io.sdio_dat(0)){
                                //被拉高,表示busy结束
                                wait_remaining := 6
                            }
                        }
                    }
                    update_clk_to_hi{}
                }
            }
        }
        val dat_write_wait:State = new State{
            whenIsActive{
                block_remaining     :=  io.block_size |>> 2         //每次传输4个字节
                l_crc.rst := False
                l_crc.en  := True
                crc_dat_ok   :=False
                crc_dat_fail := False
                send_remaining := -1
                update_clk_to_lo{
                    dat_oe := True
                    dat_o  := 0
                }
                update_clk_to_hi{
                    goto(dat_write)
                }
            }
        }
    }

    //接收数据流
    val recv_stream_payload = Reg(Bits(32+1 bits)) init(0)
    io.recv_stream.payload  := recv_stream_payload(31 downto 0)
    io.recv_stream.valid    := recv_stream_payload(32).rise && fsm.isActive(fsm.dat_recv)
    io.wait_rsp := fsm.isActive(fsm.dat_recv_wait) || fsm.isActive(fsm.rsp_wait) || fsm.isActive(fsm.dat_write_rsp)
    io.wait_is_rsp := fsm.isActive(fsm.rsp_wait)

    fsm.setName("fsm")
    io.cmd_busy := !fsm.isActive(fsm.idle)
}

case class sdio() extends Component {
    //定义IO
    setDefinitionName("xsdio")
    val io = new Bundle {
      val sdio_clk = out Bool()
      val sdio_cmd = inout(Analog(Bits(1 bits)))
      val sdio_dat = inout(Analog(Bits(4 bits)))

      //命令控制
      val mmc_init     = in Bool()
      val sdio_cmd_en   = in Bool()
      val sdio_cmd_valu = in UInt(6 bits)
      val sdio_cmd_argu = in UInt(32 bits)
      val sdio_cmd_need_rsp = in Bool()
      val sdio_cmd_long_rsp = in Bool()
      val sdio_rsp      = out Bits(256 bits)
      val sdio_bus_4bit = in Bool()     //默认1bit

      //分频器
      val sdio_clkdiv   = in SInt(8 bits)

      ///////////////////////////////////////////////////////////
      val dat_next_en       = in Bool()                 //开启下一个数据处理,用于多块处理,如果是sdio_dat_write开启,则进入写入状态
      //数据控制
      val block_size        = in SInt(16 bits)          //最大支持32KByte块传输,实际上默认为512字节
      val sdio_dat_en       = in Bool()
      val sdio_dat_write    = in Bool()

      //////////////////////////////////////////////////////
      //数据接收处理
      //使用Stream来传输,
      val recv_stream       = master Stream(Bits(32 bits))
      val send_stream       = slave  Stream(Bits(32 bits))
      /////////////////////////////////////////////////////////////

      //时钟处理
      val timeout_tick      = in UInt(32 bits)
      val timeout_reset     = in Bool()

      //状态输出
      val busy              = out Bool()
      val cmd_send_done     = out Bool()
      val crc_rsp_ok        = out Bool()
      val crc_dat_ok        = out Bool()
      val crc_rsp_fail      = out Bool()
      val crc_dat_fail      = out Bool()
      val timeout           = out Bool()
      val timeout_rsp       = out Bool()
      val timeout_dat       = out Bool()
      val dat_end           = out Bool()

      //debug
      val debug_flg        = out Bool()
    }

    def run(){

        //io.busy              := False
        //io.cmd_send_done     := False
        // io.crc_rsp_ok        := False
        // io.crc_rsp_fail      := False
        // io.crc_dat_ok        := False
        // io.crc_dat_fail      := False
        // io.timeout           := False
        // io.timeout_rsp       := False
        // io.timeout_dat       := False
        //io.dat_end           := False
        io.debug_flg         := False
        //io.sdio_rsp          := B"256'd0"

        // io.recv_stream.valid    := False
        // io.recv_stream.payload  := B"32'd0"
        // io.send_stream.ready    := False

        val ctrl = new sdio_ctrl()
        io.sdio_clk := ctrl.io.sdio_clk
        io.sdio_cmd := ctrl.io.sdio_cmd
        io.sdio_dat := ctrl.io.sdio_dat
        ctrl.io.cmd  := io.sdio_cmd_valu.asBits
        ctrl.io.argu := io.sdio_cmd_argu.asBits
        ctrl.io.cmd_en := io.sdio_cmd_en
        ctrl.io.need_rsp := io.sdio_cmd_need_rsp
        ctrl.io.long_rsp := io.sdio_cmd_long_rsp
        ctrl.io.sdio_clkdiv := io.sdio_clkdiv
        ctrl.io.block_size := io.block_size
        ctrl.io.bus_4bit := io.sdio_bus_4bit
        ctrl.io.data_en := io.sdio_dat_en
        ctrl.io.dat_next_en := io.dat_next_en
        ctrl.io.data_write := io.sdio_dat_write
        ctrl.io.mmc_init := io.mmc_init

        //处理收发数据
        io.recv_stream.payload := ctrl.io.recv_stream.payload
        io.recv_stream.valid :=   ctrl.io.recv_stream.valid
        ctrl.io.recv_stream.ready := io.recv_stream.ready

        ctrl.io.send_stream.payload := io.send_stream.payload
        ctrl.io.send_stream.valid :=   io.send_stream.valid
        io.send_stream.ready := ctrl.io.send_stream.ready

        //处理状态标志
        io.crc_rsp_ok        := ctrl.io.crc_rsp_ok
        io.crc_rsp_fail      := ctrl.io.crc_rsp_fail
        io.crc_dat_ok        := ctrl.io.crc_dat_ok
        io.crc_dat_fail      := ctrl.io.crc_dat_fail
        io.sdio_rsp          := ctrl.io.rsp

        //发送完成
        io.cmd_send_done := ctrl.io.cmd_done

        //空闲标志
        io.busy := ctrl.io.cmd_busy

        //处理超时设置
        val tick_cnt = Reg(SInt(32 bits)) init(0)
        val timeout_rsp = Reg(Bool) init(False)
        val timeout_dat = Reg(Bool) init(False)
        val dat_end     = Reg(Bool) init(False)


        io.timeout      := tick_cnt >= io.timeout_tick.asSInt
        io.timeout_rsp  := timeout_rsp
        io.timeout_dat  := timeout_dat
        io.dat_end      := dat_end

        val dat_send_done = (ctrl.io.crc_dat_ok | ctrl.io.crc_dat_fail)

        def update_dat_end(){
            when(io.sdio_dat_en){
                when(io.busy.rise){
                    //如果处于忙碌状态,数据结束被关闭
                    dat_end := False
                }
                .elsewhen(dat_send_done.rise){
                    //无论数据是否正确或者错误,都表示结束
                    dat_end := True
                }
            }
        }

        update_dat_end()
        when(io.timeout_reset){
            //超时计数重置
            tick_cnt := 0
        }
        .elsewhen(ctrl.io.wait_rsp){
            //如果正处理等待,则开始计时
            when(tick_cnt<io.timeout_tick.asSInt){
                tick_cnt := tick_cnt + 1
            }
            .otherwise{
                timeout_rsp := ctrl.io.wait_is_rsp
                timeout_dat := !ctrl.io.wait_is_rsp
            }
        }
        .otherwise{
            //关闭超时
            tick_cnt    := 0
            timeout_rsp := False
        }

    }

    run()
}

object Asdio {
    def main(args:Array[String]){
        //SpinalVerilog(new sdio)//.printPruned()
        var xsdio = new sdio
        SpinalConfig(
            mode=Verilog,
            //obfuscateNames=False
        ).generate(xsdio)
    }
}


